package com.skyjing.askit.view

import android.animation.ValueAnimator
import android.animation.ValueAnimator.AnimatorUpdateListener
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.util.AttributeSet
import android.util.TypedValue
import android.view.View
import android.view.animation.LinearInterpolator

//音乐律动按钮
class RhythmView @JvmOverloads constructor(
    context: Context?,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
    private lateinit var linePaint: Paint
    private var basePostion1 = 0
    private var basePostion2 = 0
    private var basePostion3 = 0
    private var basePostion4 = 0
    private var countRange = 0
    private var countPostion1 = 0
    private var countPostion2 = 0
    private var countPostion3 = 0
    private var countPostion4 = 0
    private var line1Width = 0
    private var line2Width = 0
    private var line3Width = 0
    private var line4Width = 0
    private var baseHeight = 0
    private lateinit var positiveAnim: ValueAnimator
    var duration = 500
        private set
    private val lineColor = Color.parseColor("#954584")
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        val minimumWidth = suggestedMinimumWidth
        val minimumHeight = suggestedMinimumHeight
        val width: Int
        val height: Int
        width = measureWidth(minimumWidth, widthMeasureSpec)
        height = measureHeight(minimumHeight, heightMeasureSpec)
        setMeasuredDimension(width, height)
    }

    private fun measureWidth(defaultWidth: Int, measureSpec: Int): Int {
        var defaultWidth = defaultWidth
        val specMode = MeasureSpec.getMode(measureSpec)
        val specSize = MeasureSpec.getSize(measureSpec)
        defaultWidth = when (specMode) {
            MeasureSpec.AT_MOST -> dp2px(28f) + paddingLeft + paddingRight
            MeasureSpec.EXACTLY -> specSize
            MeasureSpec.UNSPECIFIED -> Math.max(defaultWidth, specSize)
            else -> dp2px(28f) + paddingLeft + paddingRight
        }
        return defaultWidth
    }

    private fun measureHeight(defaultHeight: Int, measureSpec: Int): Int {
        var defaultHeight = defaultHeight
        val specMode = MeasureSpec.getMode(measureSpec)
        val specSize = MeasureSpec.getSize(measureSpec)
        defaultHeight = when (specMode) {
            MeasureSpec.AT_MOST -> dp2px(40f) + paddingTop + paddingBottom
            MeasureSpec.EXACTLY -> specSize
            MeasureSpec.UNSPECIFIED -> Math.max(defaultHeight, specSize)
            else -> dp2px(40f) + paddingTop + paddingBottom
        }
        return defaultHeight
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        line1Width = (w * 0.20f).toInt()
        line2Width = (w * 0.40f).toInt()
        line3Width = (w * 0.60f).toInt()
        line4Width = (w * 0.80f).toInt()
        baseHeight = (h * 0.90f).toInt()
        countPostion1 = (h * 0.58f).toInt()
        basePostion1 = countPostion1
        countPostion2 = (h * 0.25f).toInt()
        basePostion2 = countPostion2
        countPostion3 = (h * 0.42f).toInt()
        basePostion3 = countPostion3
        countPostion4 = (h * 0.08f).toInt()
        basePostion4 = countPostion4
        countRange = (h * 0.33f).toInt()
    }

    private fun init(attrs: AttributeSet?) {
        if (attrs != null) { //            TypedArray array = this.getContext().obtainStyledAttributes(R.attr.rhy);
        }
        linePaint = Paint(Paint.ANTI_ALIAS_FLAG)
        linePaint.strokeWidth = dp2px(5f).toFloat()
        linePaint.style = Paint.Style.STROKE
        linePaint.color = lineColor
        //线头形状
        linePaint.strokeCap = Paint.Cap.ROUND
        initAnim(0f, 1f)
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        canvas.drawLine(
            line1Width.toFloat(),
            baseHeight.toFloat(),
            line1Width.toFloat(),
            countPostion1.toFloat(),
            linePaint
        )
        canvas.drawLine(
            line2Width.toFloat(),
            baseHeight.toFloat(),
            line2Width.toFloat(),
            countPostion2.toFloat(),
            linePaint
        )
        canvas.drawLine(
            line3Width.toFloat(),
            baseHeight.toFloat(),
            line3Width.toFloat(),
            countPostion3.toFloat(),
            linePaint
        )
        canvas.drawLine(
            line4Width.toFloat(),
            baseHeight.toFloat(),
            line4Width.toFloat(),
            countPostion4.toFloat(),
            linePaint
        )
    }

    fun start() {
        if (positiveAnim.isRunning) {
            stop()
        }
        positiveAnim.start()
    }

    fun stop() {
        positiveAnim.cancel()
    }

    fun pause() {
        if (positiveAnim.isRunning) {
            positiveAnim.pause()
        }
    }

    private fun initAnim(from: Float, to: Float) {
        positiveAnim = ValueAnimator.ofFloat(from, to)
        positiveAnim.duration = duration.toLong()
        positiveAnim.interpolator = LinearInterpolator()
        positiveAnim.repeatCount = -1
        positiveAnim.repeatMode = ValueAnimator.REVERSE
        positiveAnim.addUpdateListener(AnimatorUpdateListener { animation ->
            val current =
                (animation.animatedValue as Float * countRange).toInt()
            if (countPostion1 != basePostion1 - current) {
                countPostion1 = basePostion1 - current
                countPostion3 = basePostion3 - current
                countPostion2 = basePostion2 + current
                countPostion4 = basePostion4 + current
            }
            postInvalidate()
        })
    }

    private fun dp2px(dpVal: Float): Int {
        return TypedValue.applyDimension(1, dpVal, this.resources.displayMetrics).toInt()
    }

    fun setDuration(duration: Int): RhythmView {
        this.duration = duration
        return this
    }

    init {
        init(attrs)
    }
}